﻿using DGIS.Service.IService.IGeometryService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.Geometry;
using OSGeo.OGR;
using DGIS.Service.Service.CoordService;

namespace DGIS.Service.Service.GeometryService
{
    public class GeometryStructService : IGeometryStructService
    {
        public IPolygon CreatePolygon(Dictionary<int, List<IPoint>> pointsDic)
        {
            IGeometryCollection geometryCollection = new PolygonClass();

            foreach (KeyValuePair<int, List<IPoint>> item in pointsDic)
            {
                List<IPoint> points = item.Value;

                Ring ring = new RingClass();

                foreach (IPoint point in points)
                {
                    ring.AddPoint(point);
                }
                geometryCollection.AddGeometry(ring as IGeometry);
            }

            IPolygon polygon = geometryCollection as IPolygon;
            polygon.SimplifyPreserveFromTo();

            return polygon;
        }

        public IPolyline CreatePolyline(List<IPoint> points)
        {
            IGeometryCollection geometryCollection = new PolylineClass();

            ILine line = new LineClass();
            for (int i = 0; i < points.Count - 1; i++)
            {
                line.PutCoords(points[i], points[i + 1]);
            }
            ISegment segment = line as ISegment;
                        
            ISegmentCollection segmentCollection = new PathClass();
            object o = Type.Missing;
            segmentCollection.AddSegment(segment, ref o, ref o);

            geometryCollection.AddGeometry(segmentCollection as IGeometry, ref o, ref o);
            IPolyline polyline = geometryCollection as IPolyline;
            polyline.SimplifyNetwork();

            return polyline;
        }

        public Dictionary<int, List<IPoint>> GetPolygonPoints(IPolygon polygon)
        {
            Dictionary<int, List<IPoint>> dic = new Dictionary<int, List<IPoint>>();

            IGeometryCollection geometryCollection = polygon as IGeometryCollection;
            for (int i = 0; i < geometryCollection.GeometryCount; i++)
            {
                List<IPoint> points = new List<IPoint>();

                IGeometry geometry = geometryCollection.Geometry[i];

                Ring ring = geometry as Ring;
                for (int n = 0; n < ring.PointCount; n++)
                {
                    IPoint point = ring.Point[n];
                    points.Add(point);
                }

                dic.Add(i, points);
            }

            return dic;
        }

        public List<IPoint> GetPolylinePoints(IPolyline polyline)
        {
            List<IPoint> points = new List<IPoint>();

            IPointCollection pointCollection = polyline as IPointCollection;
            for (int i = 0; i < pointCollection.PointCount; i++)
            {
                IPoint point = pointCollection.Point[i];
                points.Add(point);
            }

            return points;
        }


        public List<List<double[]>> GetShpPoints(string shpPath, out string type)
        {
            List<List<double[]>> points = new List<List<double[]>>();
            type = "";

            //注册所有格式
            OSGeo.OGR.Ogr.RegisterAll();
            // 支持中文路径
            OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
            // 属性表字段支持中文 
            OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "");

            //打开本地shp文件
            DataSource dataSource = Ogr.Open(shpPath, 1);
            Layer layer = dataSource.GetLayerByIndex(0);
            OSGeo.OGR.wkbGeometryType geometryType= layer.GetGeomType();
            
            switch (geometryType)
            {
                case OSGeo.OGR.wkbGeometryType.wkbUnknown:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbPoint:
                    type = "point";
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbLineString:
                    type = "polyline";
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbPolygon:
                    type = "polygon";
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbMultiPoint:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbMultiLineString:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbMultiPolygon:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbGeometryCollection:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbNone:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbLinearRing:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbPoint25D:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbLineString25D:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbPolygon25D:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbMultiPoint25D:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbMultiLineString25D:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbMultiPolygon25D:
                    break;
                case OSGeo.OGR.wkbGeometryType.wkbGeometryCollection25D:
                    break;
                default:
                    break;
            }

            layer.ResetReading();//重新获取全部数据(消除限制条件)

            CoordConvertService coordConvertService = new CoordConvertService();

            //读取属性值
            OSGeo.OGR.Feature feature = layer.GetNextFeature();
            while (feature != null)
            {
                List<double[]> items = new List<double[]>();

                Geometry geometry=feature.GetGeometryRef().GetBoundary();
                for (int i = 0; i < geometry.GetPointCount(); i++)
                {
                    double[] point=new double[2];
                    geometry.GetPoint(i, point);
                    //point = coordConvertService.XYToLonLat(point[0], point[1]);

                    items.Add(point);
                }
                points.Add(items);

                feature.Dispose();

                feature = layer.GetNextFeature();
            }

            dataSource.Dispose();
            layer.Dispose();

            dataSource = null;
            layer = null;
            
            return points;
        }
    }
}
